package za.org.jcicada.confss.impl;


import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Properties;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import za.org.jcicada.cfgmngr.IConfigurationClient;
import za.org.jcicada.cfgmngr.IConfigurationServer;
import za.org.jcicada.cfgmngr.SystemSetType;
import za.org.jcicada.cfgmngr.impl.ConfigurationServerProxy;
import za.org.jcicada.cfgmngr.impl.PropertyLoader;
import za.org.jcicada.genss.ServiceURN;
import za.org.jcicada.genss.SystemURN;
import za.org.jcicada.genss.messages.Result;
import za.org.jcicada.genss.messages.SuccessCode;
import za.org.jcicada.genss.sensor.ISensor;
import za.org.jcicada.genss.sensor.SensorURN;
import za.org.jcicada.genss.sensor.impl.Sensor;
import za.org.jcicada.genss.sensor.impl.TypeBoolean;


public class MockConfSS extends ConfSS {
    private static final Log logger = LogFactory.getLog(MockConfSS.class);       

        private Result resultSuccess = new Result();
        private Result resultFail = new Result(SuccessCode.COMPLETE_FAILURE,"Failed");       
        
        URI testSensorURI;
        ServiceURN testSensorURN;
        public URI testURI;
      
        URI locateServiceURI;
        ServiceURN locateServiceURN;
        
        
        public class MockConfigServer extends ConfigurationServerProxy {

            MockConfSS myMockConfss;
            
            public int iCountConfigurationRequests = 0;
            public int iCountSystemRegistrationRequests = 0;
            public int iCountServiceRegistrationRequests = 0;
            public int iCountSystemDeregistrationRequests = 0;
            public int iCountServiceDeregistrationRequests = 0;
            public int iCountLocateServiceRequests = 0;
            
            public boolean autoReply = true;
            
            public MockConfigServer(MockConfSS mockConfss, URI locationURI) {
                super(locationURI);
                myMockConfss = mockConfss;
            }




            /*
             * ************************************************
             * Inject messages as if from CfgMngr
             * ************************************************
             */
            
            public boolean loadPropertiesFromFile(Properties properties, String fileName){
                boolean result = false;
                try {
                    InputStream propertiesFile = new FileInputStream(fileName);
                    properties.load(propertiesFile);
                } catch (Exception ex){
                    logger.debug("Could not load properties from " + fileName + ". Exception: " + ex);
                    return false;
                }

                return result;
            }
            
            /**
             * Inject configuration reply by loading a dynamic properties file directly
             * as if it was received from CfgMngr
             */
            public boolean injectConfigurationReply(String filename) {
                logger.debug("MockConfigServer injectConfigurationReply");
                //Read a dynamic properties file
                Properties properties = PropertyLoader.loadProperties(filename);
                try {
                    //conf.loadProperties(properties);
                    this.myMockConfss.replyGetConfiguration(resultSuccess, properties);
                    return (true);
                } catch (IllegalArgumentException e) {
                    String message = "Cannot load dynamic properties file " + filename + " for " + this.myMockConfss.getSystemName();
                    logger.fatal(message);
                    return (false);               
                }   
            }
            
            /**
             * Inject system registration reply directly as if it was received by CfgMngr
             */
            public void injectSystemRegistrationReply(boolean reregister) {
                logger.debug("MockConfigServer injectSystemRegistrationReply reregister="+(reregister?"true":"false"));
                myMockConfss.replyRegisterSystem(resultSuccess, myMockConfss.getSystemURN(), reregister);              
            }

            /**
             * Inject all that is required for Confss to become operational
             * @throws InterruptedException 
             */
            public void injectForOperational(boolean reregister) throws InterruptedException {
                //Inject Configuration reply
                Thread.sleep(500);
                injectConfigurationReply(myMockConfss.getSystemName()+DYNAMIC_PROPERTIES_FILE_PFX);

                //Inject system registration reply
                Thread.sleep(2000);
                injectSystemRegistrationReply(reregister);
                           
            }

            

            /*
             * ************************************************
             * Implement IConfigurationServer messages as if CfgMngr
             * ************************************************
             */
           
            public void injectRequestDeregisterService(IConfigurationClient client, URI locationURI, ServiceURN serviceURN) {
            logger.info("MockConfigServer requestDeregisterServices injecting reply");
            myMockConfss.replyDeregisterService(resultSuccess, locationURI, serviceURN);
            }
            
            public void requestDeregisterService(IConfigurationClient client, URI locationURI, ServiceURN serviceURN) {
                logger.debug("MockConfigServer requestDeregisterServices");
                iCountServiceDeregistrationRequests++;
                
                if (autoReply == true) {
                    injectRequestDeregisterService(client, locationURI, serviceURN);
                }

            }


            public void injectRequestDeregisterSystem(IConfigurationClient client, SystemURN systemURN) {
            logger.info("MockConfigServer requestDeregisterSystem injecting reply");
            myMockConfss.replyDeregisterSystem(resultSuccess, systemURN);
            }
            
            public void requestDeregisterSystem(IConfigurationClient client, SystemURN systemURN) {
                logger.debug("MockConfigServer requestDeregisterSystem");
                iCountSystemDeregistrationRequests++;

                if (autoReply == true) {
                    injectRequestDeregisterSystem(client, systemURN);
                }
            }


            public void injectRequestGetConfiguration(IConfigurationClient client, SystemURN systemURN) {
                logger.info("MockConfigServer requestGetConfiguration injecting reply");
                injectConfigurationReply(myMockConfss.getSystemName()+DYNAMIC_PROPERTIES_FILE_PFX);       
            }
        
            public void requestGetConfiguration(IConfigurationClient client, SystemURN systemURN) {
                logger.debug("MockConfigServer requestGetConfiguration");
                iCountConfigurationRequests++;

                if (autoReply == true) {
                    injectRequestGetConfiguration(client, systemURN);
                }

            }
            
            
            public void injectRequestLocateService(IConfigurationClient client, ServiceURN serviceURN, String protocol) {
                logger.info("MockConfigServer requestLocateService injecting reply");
                //Return this subsystem URI
                if (serviceURN.equals(testSensorURN)) {
                    myMockConfss.replyLocateService(resultSuccess, testSensorURN, myMockConfss.testURI);
                } else {
                    myMockConfss.replyLocateService(resultFail, serviceURN, myMockConfss.testURI);
                }
           }

            public void requestLocateService(IConfigurationClient client, ServiceURN serviceURN, String protocol) {
                logger.debug("MockConfigServer requestLocateService");
                iCountLocateServiceRequests++;
                
                if (autoReply == true) {
                    injectRequestLocateService(client, serviceURN, protocol);
                }
             }


            public void injectRequestRegisterService(IConfigurationClient client, URI locationURI, ServiceURN serviceURN) {
                logger.info("MockConfigServer requestRegisterServices injecting reply");
                myMockConfss.replyRegisterService(resultSuccess, locationURI, serviceURN);
            }
            
            public void requestRegisterService(IConfigurationClient client, URI locationURI, ServiceURN serviceURN) {
                logger.debug("MockConfigServer requestRegisterServices");
                iCountServiceRegistrationRequests++;

                if (autoReply == true) {
                    injectRequestRegisterService(client, locationURI, serviceURN);
                }
            }

            
            public void injectRequestRegisterSystem(IConfigurationClient client, SystemURN systemURN) {
                logger.info("MockConfigServer requestRegisterSystem injecting reply");
                myMockConfss.replyRegisterSystem(resultSuccess, systemURN, false);
            }

            public void requestRegisterSystem(IConfigurationClient client, SystemURN systemURN) {
                logger.debug("MockConfigServer requestRegisterSystem");
                iCountSystemRegistrationRequests++;

                if (autoReply == true) {
                    injectRequestRegisterSystem(client, systemURN);
                }
            }
        }
        
        public MockConfigServer mockConfigServer;  //@TODO public is temporary because duringIntialize not called?


        public MockConfSS(SystemURN systemURN, URI cfgmngrLocationURI) throws URISyntaxException {
            super(systemURN, cfgmngrLocationURI);
        }

        
        public int getRegisteredServicesCount(){
            return this.services.size();
        }
        
        
        public void addTestSensor() throws URISyntaxException {
            this.testSensorURN = this.addSensor(this.getSystemURN(), (ISensor) new Sensor(TypeBoolean.getInstance(), "test", "description", "units"));
        }

        
        
        /**
         * Initialize the extended confss before use.
         */
        public void initialize() {
            //BasicConfigurator.configure();
            logger.info("MockConfSS initialize");
            super.initialize();
        }

        /**
         * Shut down the extended confss after use.
         */
        public void shutdown() {
            logger.debug("MockConfSS shutdown");
            super.shutdown();
            //BasicConfigurator.resetConfiguration();
        }  

        /**
         * Perform specific shutdown mode actions for the extended confss
         * @see org.jcicada.genss.GenSS#duringShutdown()
         */
        public void duringShutdown() throws Exception {
            logger.debug("MockConfSS duringShutdown");
            super.duringShutdown();
        }

        //@Override
        public void replyLocateService(Result result, ServiceURN serviceURN, URI locationURI) {
            logger.debug("MockConfSS replyLocateService"); 
            if (result.getCode() == SuccessCode.COMPLETE_SUCCESS) {
                logger.debug("MockConfSS replyLocateService saving URN and URI");
                locateServiceURN = serviceURN;
                locateServiceURI = locationURI;
            }
            
        }
//        
//        @Override
//        protected ConfigurationServerProxy getMyConfigServer () {
//            return (mockConfigServer);
//        }


		public void replySystemSet(Result result, SystemSetType type, Set<SystemURN> systemURNs) {
		}


        public void replySensorSet(Result result, SystemURN systemURN, Set<SensorURN> sensorURNs) {
            // TODO Auto-generated method stub
            
        }

        @Override
        protected IConfigurationServer createConfigurationServer() {
        	return new MockConfigServer (this, this.cfgmngrLocationURI);
        }

    }
 